package cn.org.intelli.lims.o2oa.model;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.SneakyThrows;
import org.hibernate.annotations.SQLDelete;
import org.springframework.stereotype.Service;
import xyz.erupt.annotation.Erupt;
import xyz.erupt.annotation.EruptField;
import xyz.erupt.annotation.fun.DataProxy;
import xyz.erupt.annotation.query.Condition;
import xyz.erupt.annotation.sub_erupt.Filter;
import xyz.erupt.annotation.sub_erupt.Tree;
import xyz.erupt.annotation.sub_field.Edit;
import xyz.erupt.annotation.sub_field.EditType;
import xyz.erupt.annotation.sub_field.View;
import xyz.erupt.annotation.sub_field.sub_edit.ReferenceTreeType;
import xyz.erupt.annotation.sub_field.sub_edit.Search;
import xyz.erupt.core.controller.EruptDataController;
import xyz.erupt.core.controller.EruptModifyController;
import xyz.erupt.core.view.Page;
import xyz.erupt.core.view.TableQueryVo;

import javax.annotation.Resource;
import javax.persistence.*;
import java.util.*;

@Service
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "lims_org")
@SQLDelete(sql = "update lims_org set deleted = true, delete_time = now() where id = ?")
@Erupt(name = "机构信息", dataProxy = Org.class, tree = @Tree(pid = "parent.id"), orderBy = "Org.sort asc", filter = @Filter("Org.deleted = false"))
public class Org implements DataProxy<Org> {

    @Id
    @EruptField
    private String id;
    @EruptField(views = @View(title = "机构编码", sortable = true), edit = @Edit(title = "机构编码", notNull = true, search = @Search(vague = true)))
    private String code;
    @EruptField(views = @View(title = "机构名称", sortable = true), edit = @Edit(title = "机构名称", notNull = true, search = @Search(vague = true)))
    private String name;
    @ManyToOne
    @EruptField(edit = @Edit(title = "上级机构信息", type = EditType.REFERENCE_TREE, referenceTreeType = @ReferenceTreeType(pid = "parent.id")))
    private Org parent;
    @EruptField(edit = @Edit(title = "显示顺序"))
    private Integer sort;
    @Column(name = "delete_time")
    private Date deleteTime;
    private Boolean deleted = false;

    @Override
    public void beforeAdd(Org org) {
        if (org.getId() == null) {
            org.setId(UUID.randomUUID().toString());
        }
    }

    @Transient
    @Resource
    private EruptModifyController eruptModifyController;
    @Transient
    @Resource
    private EruptDataController eruptDataController;
    @Transient
    private Gson gson = new Gson();

    @Override
    public void afterAdd(Org org) {
        JsonObject eruptOrg = new JsonObject();
        eruptOrg.addProperty("code", org.getId());
        eruptOrg.addProperty("name", org.getName());
        Optional.ofNullable(org.getSort()).ifPresent(sort -> eruptOrg.addProperty("sort", sort));
        if (org.getParent() != null) {
            Long eruptParentOrgId = getEruptOrgId(org.getParent());
            if (eruptParentOrgId != null) {
                JsonObject eruptParentOrg = new JsonObject();
                eruptParentOrg.addProperty("id", eruptParentOrgId);
                eruptOrg.add("parentOrg", eruptParentOrg);
            }
        }
        eruptModifyController.addEruptData("EruptOrg", eruptOrg, null, null);
    }

    @SneakyThrows
    @Override
    public void afterUpdate(Org org) {
        JsonObject eruptOrg = new JsonObject();
        eruptOrg.addProperty("id", getEruptOrgId(org));
        eruptOrg.addProperty("code", org.getId());
        Optional.ofNullable(org.getName()).ifPresent(name -> eruptOrg.addProperty("name", name));
        Optional.ofNullable(org.getSort()).ifPresent(sort -> eruptOrg.addProperty("sort", sort));
        if (org.getParent() != null) {
            Long eruptParentOrgId = getEruptOrgId(org.getParent());
            if (eruptParentOrgId != null) {
                JsonObject eruptParentOrg = new JsonObject();
                eruptParentOrg.addProperty("id", eruptParentOrgId);
                eruptOrg.add("parentOrg", eruptParentOrg);
            }
        }
        eruptModifyController.editEruptData("EruptOrg", eruptOrg);
    }

    @Override
    public void afterDelete(Org org) {
        Long eruptOrgId = getEruptOrgId(org);
        if (eruptOrgId != null) {
            eruptModifyController.deleteEruptData("EruptOrg", eruptOrgId.toString());
        }
    }

    private Long getEruptOrgId(Org org) {
        TableQueryVo orgTableQueryVo = new TableQueryVo();
        orgTableQueryVo.setPageIndex(1);
        orgTableQueryVo.setPageSize(10);
        List<Condition> orgConditions = new ArrayList<>();
        orgConditions.add(new Condition("code", org.getId()));
        orgTableQueryVo.setCondition(orgConditions);
        Page page = eruptDataController.getEruptData("EruptOrg", orgTableQueryVo);
        Long eruptOrgId = null;
        if (page.getTotal() == 1) {
            eruptOrgId = (Long) page.getList().stream().findFirst().get().get("id");
        }
        return eruptOrgId;
    }
}
